package cn.com.blueInfo.bpm.template.repository.impl;

import cn.com.blueInfo.bpm.common.entity.BaseEntity;
import cn.com.blueInfo.bpm.common.enums.BaseDeleted;
import cn.com.blueInfo.bpm.common.repository.BaseRepository;
import cn.com.blueInfo.bpm.template.entity.WorkItem;
import cn.com.blueInfo.bpm.template.enums.WorkItemStatus;
import cn.com.blueInfo.bpm.template.mapper.WorkItemMapper;
import cn.com.blueInfo.bpm.template.repository.WorkItemRepository;
import cn.com.blueInfo.bpm.template.request.WorkItemDTO;
import cn.com.blueInfo.core.entity.CurrentLoginUserInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* 节点任务实例表 数据服务实现类
* @author suxch
* @since 2025-09-01 19:30:44
*/
@Log4j2
@Service
public class WorkItemRepositoryImpl
        extends ServiceImpl<WorkItemMapper, WorkItem>
        implements WorkItemRepository, BaseRepository<WorkItem, WorkItemDTO.QueryDTO> {

    @Autowired
    private CurrentLoginUserInfo currentLoginUserInfo;

    /**
     * 提供获取 CurrentLoginUserInfo 的方法（由实现类提供，避免接口中注入）
     * @return CurrentLoginUserInfo
     */
    @Override
    public CurrentLoginUserInfo getCurrentLoginUserInfo() {
        return currentLoginUserInfo;
    }

    /**
    * 新增节点任务实例
    * @param workItem 节点任务实例参数
    */
    @Override
    public Integer createWorkItem(WorkItem workItem) {
        return sqlExecuteResult(save(workItem));
    }

    /**
     * 批量新增节点任务实例
     * @param workItemList 节点任务实例参数列表
     */
    @Override
    public Integer batchCreateWorkItem(List<WorkItem> workItemList) {
        return sqlExecuteResult(saveBatch(workItemList), workItemList.size());
    }

    /**
    * 删除节点任务实例
    * @param workItemId 节点任务实例ID
    */
    @Override
    public Integer deleteWorkItem(Long workItemId) {
        WorkItem workItem = new WorkItem();
        workItem.setId(workItemId);
        workItem.setDeleted(BaseDeleted.DELETED);
        return sqlExecuteResult(removeById(workItem));
    }

    /**
     * 批量删除节点任务实例
     * @param workItemIdList 节点任务实例ID列表
     */
    @Override
    public Integer batchDeleteWorkItem(List<Long> workItemIdList) {
        List<WorkItem> workItemList = new ArrayList<>();
        for (Long workItemId : workItemIdList) {
            WorkItem workItem = new WorkItem();
            workItem.setId(workItemId);
            workItem.setDeleted(BaseDeleted.DELETED);
            workItemList.add(workItem);
        }
        return sqlExecuteResult(removeBatchByIds(workItemList), workItemList.size());
    }

    /**
    * 更新部分节点任务实例
    * @param workItem 节点任务实例参数
    */
    @Override
    public Integer updateWorkItemPartial(WorkItem workItem) {
        validateUpdateId(workItem.getId());
        LambdaUpdateWrapper<WorkItem> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(WorkItem::getId, workItem.getId());
        return sqlExecuteResult(update(updateWrapper));
    }

    /**
    * 更新全部节点任务实例
    * @param workItem 节点任务实例参数
    */
    @Override
    public Integer updateWorkItem(WorkItem workItem) {
        validateUpdateId(workItem.getId());
        return sqlExecuteResult(updateById(workItem));
    }

    /**
    * 查询一条节点任务实例
    * @param workItemId 节点任务实例ID
    */
    @Override
    public WorkItem getWorkItemById(Long workItemId) {
        LambdaQueryWrapper<WorkItem> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WorkItem::getId, workItemId);
        return getOne(queryWrapper);
    }

    /**
    * 分页查询节点任务实例
    * @param workItemQueryDTO 节点任务实例参数
    */
    @Override
    public Page<WorkItem> getWorkItemPage(WorkItemDTO.QueryDTO workItemQueryDTO) {
        Page<WorkItem> workItemPage = new Page<>(
                workItemQueryDTO.getPage(), workItemQueryDTO.getSize());
        LambdaQueryWrapper<WorkItem> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper(queryWrapper, workItemQueryDTO);

        BaseDeleted deleted = workItemQueryDTO.getDeleted();
        if (ObjectUtils.isNotEmpty(deleted) && deleted.equals(BaseDeleted.DELETED)) {
            return baseMapper.selectDeletePage(workItemPage, queryWrapper);
        } else {
            return page(workItemPage, queryWrapper);
        }
    }

    /**
     * 根据条件查询 节点任务实例 数量
     * @param workItemQueryDTO 节点任务实例参数
     */
    @Override
    public Long getWorkItemCount(WorkItemDTO.QueryDTO workItemQueryDTO) {
        LambdaQueryWrapper<WorkItem> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper(queryWrapper, workItemQueryDTO);

        BaseDeleted deleted = workItemQueryDTO.getDeleted();
        if (ObjectUtils.isNotEmpty(deleted) && deleted.equals(BaseDeleted.DELETED)) {
            return baseMapper.selectDeleteCount(queryWrapper);
        } else {
            return count(queryWrapper);
        }
    }

    /**
     * 根据条件查询 节点任务实例
     * @param workItemQueryDTO 节点任务实例参数
     */
    @Override
    public List<WorkItem> getWorkItemList(WorkItemDTO.QueryDTO workItemQueryDTO) {
        LambdaQueryWrapper<WorkItem> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper(queryWrapper, workItemQueryDTO);

        BaseDeleted deleted = workItemQueryDTO.getDeleted();
        if (ObjectUtils.isNotEmpty(deleted) && deleted.equals(BaseDeleted.DELETED)) {
            return baseMapper.selectDeleteList(queryWrapper);
        } else {
            return list(queryWrapper);
        }
    }

    private void queryWrapper(LambdaQueryWrapper<WorkItem> queryWrapper, WorkItemDTO.QueryDTO workItemQueryDTO) {

        Long instanceId = workItemQueryDTO.getInstanceId();
        queryWrapper.eq(ObjectUtils.isNotEmpty(instanceId), WorkItem::getInstanceId, instanceId);

        Long nodeId = workItemQueryDTO.getNodeId();
        queryWrapper.eq(ObjectUtils.isNotEmpty(nodeId), WorkItem::getNodeId, nodeId);

        String nodeCode = workItemQueryDTO.getNodeCode();
        queryWrapper.eq(StringUtils.isNotBlank(nodeCode), WorkItem::getNodeCode, nodeCode);

        String nodeType = workItemQueryDTO.getNodeType();
        queryWrapper.eq(StringUtils.isNotBlank(nodeType), WorkItem::getNodeType, nodeType);

        Long handlerId = workItemQueryDTO.getHandlerId();
        queryWrapper.eq(ObjectUtils.isNotEmpty(handlerId), WorkItem::getHandlerId, handlerId);

        String handlerName = workItemQueryDTO.getHandlerName();
        queryWrapper.eq(StringUtils.isNotBlank(handlerName), WorkItem::getHandlerName, handlerName);

        WorkItemStatus workItemStatus = workItemQueryDTO.getWorkItemStatus();
        queryWrapper.eq(ObjectUtils.isNotEmpty(workItemStatus), WorkItem::getWorkItemStatus, workItemStatus);

        String viewPath = workItemQueryDTO.getViewPath();
        queryWrapper.eq(StringUtils.isNotBlank(viewPath), WorkItem::getViewPath, viewPath);

        LocalDateTime startTime = workItemQueryDTO.getStartTime();
        queryWrapper.eq(ObjectUtils.isNotEmpty(startTime), WorkItem::getStartTime, startTime);

        LocalDateTime completeTime = workItemQueryDTO.getCompleteTime();
        queryWrapper.eq(ObjectUtils.isNotEmpty(completeTime), WorkItem::getCompleteTime, completeTime);

        String opinion = workItemQueryDTO.getOpinion();
        queryWrapper.eq(StringUtils.isNotBlank(opinion), WorkItem::getOpinion, opinion);

        String decision = workItemQueryDTO.getDecision();
        queryWrapper.eq(StringUtils.isNotBlank(decision), WorkItem::getDecision, decision);

        Long prevNodeId = workItemQueryDTO.getPrevNodeId();
        queryWrapper.eq(ObjectUtils.isNotEmpty(prevNodeId), WorkItem::getPrevNodeId, prevNodeId);

        Long prevWorkItemId = workItemQueryDTO.getPrevWorkItemId();
        queryWrapper.eq(ObjectUtils.isNotEmpty(prevWorkItemId), WorkItem::getPrevWorkItemId, prevWorkItemId);

        Long prevHandlerId = workItemQueryDTO.getPrevHandlerId();
        queryWrapper.eq(ObjectUtils.isNotEmpty(prevHandlerId), WorkItem::getPrevHandlerId, prevHandlerId);

        addQueryWrapper(queryWrapper, workItemQueryDTO, getCommonColumn());

    }

    private Map<String, SFunction<WorkItem, ?>> getCommonColumn() {
        return BaseEntity.getCommonColumn(
                WorkItem::getOrderNumber,
                WorkItem::getTenantId,
                WorkItem::getApplicationId,
                WorkItem::getStatus,
                WorkItem::getDeleted,
                WorkItem::getDeleteUserId,
                WorkItem::getDeleteTime,
                WorkItem::getRemark,
                WorkItem::getCreateUserId,
                WorkItem::getCreateTime,
                WorkItem::getUpdateUserId,
                WorkItem::getUpdateTime,
                WorkItem::getExtend1,
                WorkItem::getExtend2,
                WorkItem::getExtend3);
    }

}
